Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for globs in probe.resolvers.intellij.repositories config #285

Conversation

LukaszKontowski
Copy link
Contributor

@LukaszKontowski LukaszKontowski commented Sep 26, 2022

Closes #250
work in progress

to be done:

  • add description and some example for users in reference.conf
  • add one more test scenario to test new logic with multiple paths (but only one is valid)

@LukaszKontowski LukaszKontowski self-assigned this Sep 26, 2022
@LukaszKontowski LukaszKontowski changed the title Feature/enable globs in repositories config Allow for globs in probe.resolvers.intellij.repositories config Sep 26, 2022
private def replaceFirstFoundWildcardWithDirectories(path: String): List[String] = {
def removeLastFileSeparator(path: String): String = if (path.endsWith("/")) path.init else path

val pathUntilWildcard = Paths.get(path.substring(0, path.indexOf('*')).replace("file:", ""))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay... so a ready library for globs wasn't an adequate solution here? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not manage to test these libraries yet. Wanted to have a working solution first. I'm not sure if we need them here. Suggested docs https://docs.oracle.com/javase/tutorial/essential/io/find.html don't seem helpful to me in this case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, leaving up to your judgement

@LukaszKontowski LukaszKontowski marked this pull request as ready for review September 27, 2022 16:16
@@ -109,6 +109,21 @@ probe {
// ~/.pluginVerifier/ides/IC-[revision]/ directory (if exists). If it does not exist under specified path,
// then ide-probe will download it from one of the 6 official repositories.
//
// If your config contains a pattern pointing to an IntelliJ instance that exists on local filesystem, then you
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:benissimo: the doc


private def pathMightBeValidResource(path: String): Boolean =
path.indexOf('*') == -1 &&
(path.endsWith(".zip") ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't it too specific check? Filling extension is responsibility of pattern replacement that already happened.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the check is needed to find proper path from multiple directories that exist in place of * (some are not valid).
But I just realised that this check is not valid. This check should return true only when path ends properly, as defined in the pattern... Let me fix this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, logic of pathMightBeValidResource method is fixed now.

def removeLastFileSeparator(path: String): String = if (path.endsWith("/")) path.init else path

val pathUntilWildcard = Paths.get(path.substring(0, path.indexOf('*')).replace("file:", ""))
val stringPathAfterWildcard = path.substring(path.indexOf('*') + 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you use split for that? It allows to specify limit of splits.

Copy link
Contributor Author

@LukaszKontowski LukaszKontowski Oct 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but then I would have to use three vals instead of two:

val Array(stringPathUntilWildcard, stringPathAfterWildcard) = path.split("*", 2)
val pathUntilWildcard = Paths.get(stringPathUntilWildcard.replace("file:", ""))

If you think that would be better than current solution, I can do that. Let me know, what do you think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's do this. It is same number of lines, but 2 substring calls with some index offset are more complex for reading and understanding than a simple split.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a problem connected to replacing String#indexOf with String#split
The String#split(String regex, int limit) method treats the String parameter "*" as a regular expression, which leads to invalid results.

I would suggest to switch back to previous logic:

val pathUntilWildcard = Paths.get(path.substring(0, path.indexOf('*')).replace("file:", ""))
val stringPathAfterWildcard = path.substring(path.indexOf('*') + 1)

to be sure that * wildcard will not be used as a regular expression.

Copy link
Contributor

@lukaszwawrzyk lukaszwawrzyk Oct 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be sure, just use regex as expected r"\*" or "[*]"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, but the thing is - I don't want java String's method to treat the * as a regular expression. And String#split by default treats the String parameter as a regular expression. That's why I want to stick to current logic, without using split. So that * will never be treated as a regex.

@LukaszKontowski LukaszKontowski marked this pull request as draft October 14, 2022 15:30
@LukaszKontowski

This comment was marked as outdated.

@LukaszKontowski LukaszKontowski marked this pull request as ready for review October 17, 2022 13:26
@LukaszKontowski LukaszKontowski marked this pull request as draft October 17, 2022 15:39
@LukaszKontowski LukaszKontowski marked this pull request as ready for review October 17, 2022 20:55
@LukaszKontowski
Copy link
Contributor Author

LukaszKontowski commented Oct 18, 2022

Added two empty files to test resources so that resolvesIntelliJPatternWithGlobesUsed test will check if our logic works properly - chooses the proper file and not one of two invalid paths.


// Solution below assumes that each * character is used to mark one part of the path (one atomic directory),
// for example: "file:///home/.cache/ides/com.jetbrains.intellij.idea/ideaIC/[revision]/*/ideaIC-[revision]/".
// Wildcard character should NOT be used as the last element of the pattern - to avoid ambiguous results.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm technically, ambiguous results can also happen when wildcard is somewhere inside the path as well, right?

Maybe sth like:

Suggested change
// Wildcard character should NOT be used as the last element of the pattern - to avoid ambiguous results.
// Wildcard character should NOT be used as the last element of the pattern - to decrease the probability of getting ambiguous results.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ambiguous results can also happen when wildcard is somewhere inside the path as well, right?

No, if the * wildcard is used in replacement of an atomic directory from the path (but not the last part) - then

private def resolveGlobsInPattern(pathPattern: String): String =
    replaceGlobsWithExistingDirectories(List(pathPattern), pathPattern).head
  • will return only one element if pattern is valid (so the result will not be ambiguous)
    or
  • will throw NoSuchElementException if pattern is not valid

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh okay... so let's break down all cases:

  1. zero glob matches: exception regardless of where the glob is located?
  2. exactly one glob match: OK
  3. more than one glob match:
    a. if * is used for the last part of the glob — multiple results returned?
    b. if * is used for other part of the glob — exception thrown?

Copy link
Contributor Author

@LukaszKontowski LukaszKontowski Oct 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Answered in PMs but short answers below:

  1. zero glob matches: exception regardless of where the glob is located?

NoSuchElementException will be thrown (as pattern is not valid - such file does not exist)

  1. exactly one glob match: OK

yes

  1. more than one glob match:
    a. if * is used for the last part of the glob — multiple results returned?

no - NoSuchElementException will be thrown - using * as the last element of the path is not possible, because then the logic would not be able to choose the proper path.
For example - if we would have path endings like below:

.../df364b7662aeb20ca2eafead730380017c395661/ideaIC-223.4884.69-EAP-SNAPSHOT 
.../df364b7662aeb20ca2eafead730380017c395661/ideaIC-223.4884.69-EAP-SNAPSHOT.zip
.../df364b7662aeb20ca2eafead730380017c395661/ideaIC-223.4884.69-EAP-SNAPSHOT.jar
.../df364b7662aeb20ca2eafead730380017c395661/ideaIC-223.4884.69-EAP-SNAPSHOT.pom

where first one is directory and second one - a .zip file - and the pattern ends with * - how can we know, which one should be used?

  1. more than one glob match:
    b. if * is used for other part of the glob — exception thrown?

no - resolveGlobsInPattern will choose the first one by calling .head

@LukaszKontowski LukaszKontowski merged commit 3cdb91e into VirtusLab:master Oct 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow for globs in probe.resolvers.intellij.repositories config
3 participants